var k = Object.defineProperty;
var x = (c, t, e) =>
  t in c
    ? k(c, t, { enumerable: !0, configurable: !0, writable: !0, value: e })
    : (c[t] = e);
var o = (c, t, e) => (x(c, typeof t != 'symbol' ? t + '' : t, e), e);
import { Alias as D } from '../nodes/Alias.js';
import {
  isEmptyPath as m,
  collectionFromPath as b,
} from '../nodes/Collection.js';
import {
  NODE_TYPE as S,
  DOC as p,
  isNode as P,
  isCollection as a,
  isScalar as J,
} from '../nodes/identity.js';
import { Pair as T } from '../nodes/Pair.js';
import { toJS as M } from '../nodes/toJS.js';
import { Schema as B } from '../schema/Schema.js';
import { stringifyDocument as K } from '../stringify/stringifyDocument.js';
import {
  anchorNames as _,
  findNewAnchor as C,
  createNodeAnchors as L,
} from './anchors.js';
import { applyReviver as Y } from './applyReviver.js';
import { createNode as q } from './createNode.js';
import { Directives as w } from './directives.js';
class N {
  constructor(t, e, s) {
    /** A comment before this Document */
    o(this, 'commentBefore', null);
    /** A comment immediately after this Document */
    o(this, 'comment', null);
    /** The document contents. */
    o(this, 'contents');
    o(this, 'directives');
    /** Errors encountered during parsing. */
    o(this, 'errors', []);
    o(this, 'options');
    /** Warnings encountered during parsing. */
    o(this, 'warnings', []);
    Object.defineProperty(this, S, { value: p });
    let n = null;
    typeof e == 'function' || Array.isArray(e)
      ? (n = e)
      : s === void 0 && e && ((s = e), (e = void 0));
    const i = Object.assign(
      {
        intAsBigInt: !1,
        keepSourceTokens: !1,
        logLevel: 'warn',
        prettyErrors: !0,
        strict: !0,
        uniqueKeys: !0,
        version: '1.2',
      },
      s,
    );
    this.options = i;
    let { version: r } = i;
    s != null && s._directives
      ? ((this.directives = s._directives.atDocument()),
        this.directives.yaml.explicit && (r = this.directives.yaml.version))
      : (this.directives = new w({ version: r })),
      this.setSchema(r, s),
      (this.contents = t === void 0 ? null : this.createNode(t, n, s));
  }
  /**
   * Create a deep copy of this Document and its contents.
   *
   * Custom Node values that inherit from `Object` still refer to their original instances.
   */
  clone() {
    const t = Object.create(N.prototype, {
      [S]: { value: p },
    });
    return (
      (t.commentBefore = this.commentBefore),
      (t.comment = this.comment),
      (t.errors = this.errors.slice()),
      (t.warnings = this.warnings.slice()),
      (t.options = Object.assign({}, this.options)),
      this.directives && (t.directives = this.directives.clone()),
      (t.schema = this.schema.clone()),
      (t.contents = P(this.contents)
        ? this.contents.clone(t.schema)
        : this.contents),
      this.range && (t.range = this.range.slice()),
      t
    );
  }
  /** Adds a value to the document. */
  add(t) {
    h(this.contents) && this.contents.add(t);
  }
  /** Adds a value to the document. */
  addIn(t, e) {
    h(this.contents) && this.contents.addIn(t, e);
  }
  /**
   * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
   *
   * If `node` already has an anchor, `name` is ignored.
   * Otherwise, the `node.anchor` value will be set to `name`,
   * or if an anchor with that name is already present in the document,
   * `name` will be used as a prefix for a new unique anchor.
   * If `name` is undefined, the generated anchor will use 'a' as a prefix.
   */
  createAlias(t, e) {
    if (!t.anchor) {
      const s = _(this);
      t.anchor = !e || s.has(e) ? C(e || 'a', s) : e;
    }
    return new D(t.anchor);
  }
  createNode(t, e, s) {
    let n;
    if (typeof e == 'function') (t = e.call({ '': t }, '', t)), (n = e);
    else if (Array.isArray(e)) {
      const E = v =>
          typeof v == 'number' || v instanceof String || v instanceof Number,
        y = e.filter(E).map(String);
      y.length > 0 && (e = e.concat(y)), (n = e);
    } else s === void 0 && e && ((s = e), (e = void 0));
    const {
        aliasDuplicateObjects: i,
        anchorPrefix: r,
        flow: l,
        keepUndefined: f,
        onTagObj: u,
        tag: d,
      } = s ?? {},
      { onAnchor: A, setAnchors: O, sourceObjects: I } = L(this, r || 'a'),
      j = {
        aliasDuplicateObjects: i ?? !0,
        keepUndefined: f ?? !1,
        onAnchor: A,
        onTagObj: u,
        replacer: n,
        schema: this.schema,
        sourceObjects: I,
      },
      g = q(t, d, j);
    return l && a(g) && (g.flow = !0), O(), g;
  }
  /**
   * Convert a key and a value into a `Pair` using the current schema,
   * recursively wrapping all values as `Scalar` or `Collection` nodes.
   */
  createPair(t, e, s = {}) {
    const n = this.createNode(t, null, s),
      i = this.createNode(e, null, s);
    return new T(n, i);
  }
  /**
   * Removes a value from the document.
   * @returns `true` if the item was found and removed.
   */
  delete(t) {
    return h(this.contents) ? this.contents.delete(t) : !1;
  }
  /**
   * Removes a value from the document.
   * @returns `true` if the item was found and removed.
   */
  deleteIn(t) {
    return m(t)
      ? this.contents == null
        ? !1
        : ((this.contents = null), !0)
      : h(this.contents)
        ? this.contents.deleteIn(t)
        : !1;
  }
  /**
   * Returns item at `key`, or `undefined` if not found. By default unwraps
   * scalar values from their surrounding node; to disable set `keepScalar` to
   * `true` (collections are always returned intact).
   */
  get(t, e) {
    return a(this.contents) ? this.contents.get(t, e) : void 0;
  }
  /**
   * Returns item at `path`, or `undefined` if not found. By default unwraps
   * scalar values from their surrounding node; to disable set `keepScalar` to
   * `true` (collections are always returned intact).
   */
  getIn(t, e) {
    return m(t)
      ? !e && J(this.contents)
        ? this.contents.value
        : this.contents
      : a(this.contents)
        ? this.contents.getIn(t, e)
        : void 0;
  }
  /**
   * Checks if the document includes a value with the key `key`.
   */
  has(t) {
    return a(this.contents) ? this.contents.has(t) : !1;
  }
  /**
   * Checks if the document includes a value at `path`.
   */
  hasIn(t) {
    return m(t)
      ? this.contents !== void 0
      : a(this.contents)
        ? this.contents.hasIn(t)
        : !1;
  }
  /**
   * Sets a value in this document. For `!!set`, `value` needs to be a
   * boolean to add/remove the item from the set.
   */
  set(t, e) {
    this.contents == null
      ? (this.contents = b(this.schema, [t], e))
      : h(this.contents) && this.contents.set(t, e);
  }
  /**
   * Sets a value in this document. For `!!set`, `value` needs to be a
   * boolean to add/remove the item from the set.
   */
  setIn(t, e) {
    m(t)
      ? (this.contents = e)
      : this.contents == null
        ? (this.contents = b(this.schema, Array.from(t), e))
        : h(this.contents) && this.contents.setIn(t, e);
  }
  /**
   * Change the YAML version and schema used by the document.
   * A `null` version disables support for directives, explicit tags, anchors, and aliases.
   * It also requires the `schema` option to be given as a `Schema` instance value.
   *
   * Overrides all previously set schema options.
   */
  setSchema(t, e = {}) {
    typeof t == 'number' && (t = String(t));
    let s;
    switch (t) {
      case '1.1':
        this.directives
          ? (this.directives.yaml.version = '1.1')
          : (this.directives = new w({ version: '1.1' })),
          (s = { merge: !0, resolveKnownTags: !1, schema: 'yaml-1.1' });
        break;
      case '1.2':
      case 'next':
        this.directives
          ? (this.directives.yaml.version = t)
          : (this.directives = new w({ version: t })),
          (s = { merge: !1, resolveKnownTags: !0, schema: 'core' });
        break;
      case null:
        this.directives && delete this.directives, (s = null);
        break;
      default: {
        const n = JSON.stringify(t);
        throw new Error(
          `Expected '1.1', '1.2' or null as first argument, but found: ${n}`,
        );
      }
    }
    if (e.schema instanceof Object) this.schema = e.schema;
    else if (s) this.schema = new B(Object.assign(s, e));
    else
      throw new Error(
        'With a null YAML version, the { schema: Schema } option is required',
      );
  }
  // json & jsonArg are only used from toJSON()
  toJS({
    json: t,
    jsonArg: e,
    mapAsMap: s,
    maxAliasCount: n,
    onAnchor: i,
    reviver: r,
  } = {}) {
    const l = {
        anchors: /* @__PURE__ */ new Map(),
        doc: this,
        keep: !t,
        mapAsMap: s === !0,
        mapKeyWarned: !1,
        maxAliasCount: typeof n == 'number' ? n : 100,
      },
      f = M(this.contents, e ?? '', l);
    if (typeof i == 'function')
      for (const { count: u, res: d } of l.anchors.values()) i(d, u);
    return typeof r == 'function' ? Y(r, { '': f }, '', f) : f;
  }
  /**
   * A JSON representation of the document `contents`.
   *
   * @param jsonArg Used by `JSON.stringify` to indicate the array index or
   *   property name.
   */
  toJSON(t, e) {
    return this.toJS({ json: !0, jsonArg: t, mapAsMap: !1, onAnchor: e });
  }
  /** A YAML representation of the document. */
  toString(t = {}) {
    if (this.errors.length > 0)
      throw new Error('Document with errors cannot be stringified');
    if (
      'indent' in t &&
      (!Number.isInteger(t.indent) || Number(t.indent) <= 0)
    ) {
      const e = JSON.stringify(t.indent);
      throw new Error(`"indent" option must be a positive integer, not ${e}`);
    }
    return K(this, t);
  }
}
function h(c) {
  if (a(c)) return !0;
  throw new Error('Expected a YAML collection as document contents');
}
export { N as Document };
